home *** CD-ROM | disk | FTP | other *** search
/ The Very Best of Atari Inside / The Very Best of Atari Inside 1.iso / mint / mint110s / xbios.c < prev    next >
C/C++ Source or Header  |  1993-09-08  |  7KB  |  306 lines

  1. /*
  2. Copyright 1990,1991,1992 Eric R. Smith.
  3. Copyright 1992,1993 Atari Corporation.
  4. All rights reserved.
  5. */
  6.  
  7. /*
  8.  * XBIOS replacement routines
  9.  */
  10.  
  11. #include "mint.h"
  12.  
  13. extern int tosvers;    /* from main.c */
  14.  
  15. #define XBIOS_MAX 0x80
  16.  
  17. Func xbios_tab[XBIOS_MAX];    /* initially all zeros */
  18. short xbios_max = XBIOS_MAX;
  19.  
  20. /* NOTE: has_bconmap is initialized in main.c */
  21.  
  22. int has_bconmap;    /* flag: set if running under a version
  23.              * of TOS which supports Bconmap
  24.              */
  25.  
  26. /*
  27.  * Supexec() presents a lot of problems for us: for example, the user
  28.  * may be calling the kernel, or may be changing interrupt vectors
  29.  * unexpectedly. So we play some dirty tricks here: the function
  30.  * call is treated like a signal handler, and we take advantage
  31.  * of the fact that no context switches will take place while
  32.  * in supervisor mode. ASSUMPTION: the user will not choose to
  33.  * switch back to user mode, or if s/he does it will be as part
  34.  * of a longjmp().
  35.  *
  36.  * BUG: if the user function switches to user mode, then back to
  37.  * supervisor mode and returns, then the returned value may be
  38.  * inaccurate (this happens if two programs make Supexec calls
  39.  * at the same time).
  40.  */
  41.  
  42. long ARGS_ON_STACK (*usrcall) P_((long, long,long,long,long,long));
  43. long usrret;
  44. long usrarg1, usrarg2, usrarg3, usrarg4, usrarg5;
  45.  
  46. #if 0
  47. /* moved to syscall.spp */
  48. static void ARGS_ON_STACK do_usrcall P_((void));
  49.  
  50. static void ARGS_ON_STACK
  51. do_usrcall()
  52. {
  53.     usrret = (*usrcall)((long)usrcall, usrarg1, usrarg2, usrarg3, usrarg4,
  54.          usrarg5);
  55. }
  56. #endif
  57.  
  58. long ARGS_ON_STACK
  59. supexec(funcptr, arg1, arg2, arg3, arg4, arg5)
  60.     Func funcptr;
  61.     long arg1, arg2, arg3, arg4, arg5;
  62. {
  63.     short savesr;
  64.     CONTEXT *syscall = &curproc->ctxt[SYSCALL];
  65.  
  66. /* set things up so that "signal 0" will be handled by calling the user's
  67.  * function.
  68.  */
  69.  
  70.     usrcall = funcptr;
  71.     usrarg1 = arg1;
  72.     usrarg2 = arg2;
  73.     usrarg3 = arg3;
  74.     usrarg4 = arg4;
  75.     usrarg5 = arg5;
  76.     curproc->sighandle[0] = (long)do_usrcall;
  77.     savesr = syscall->sr;    /* save old super/user mode flag */
  78.     syscall->sr |= 0x2000;    /* set supervisor mode */
  79.     handle_sig(0);        /* actually call out to the user function */
  80.     syscall->sr = savesr;
  81.  
  82. /* do_usrcall saves the user's return value in usrret */
  83.     return usrret;
  84. }
  85.  
  86.  
  87. /*
  88.  * midiws: we have to replace this, because it's possible that the process'
  89.  * view of what the MIDI port is has been changed by Fforce or Fmidipipe
  90.  */
  91.  
  92. long ARGS_ON_STACK
  93. midiws(cnt, buf)
  94.     int cnt;
  95.     const char *buf;
  96. {
  97.     FILEPTR *f;
  98.     long towrite = cnt+1;
  99.  
  100.     f = curproc->handle[-5];    /* MIDI output handle */
  101.     if (!f) return EIHNDL;
  102.  
  103.     if (is_terminal(f)) {
  104.         while (cnt >= 0) {
  105.             tty_putchar(f, (long)*buf, RAW);
  106.             buf++; cnt--;
  107.         }
  108.         return towrite;
  109.     }
  110.     return (*f->dev->write)(f, buf, towrite);
  111. }
  112.  
  113. /*
  114.  * Modem control things: these are replaced because we handle
  115.  * Bconmap ourselves
  116.  */
  117.  
  118. /* mapin: utility routine, does a Bconmap and keeps track
  119.  * so we call the kernel only when necessary; call this
  120.  * only if has_bconmap is "true".
  121.  * Returns: 0 on failure, 1 on success.
  122.  */
  123. int curbconmap;
  124.  
  125. int
  126. mapin(dev)
  127.     int dev;
  128. {
  129.     long r;
  130.  
  131.     if (dev == curbconmap)
  132.         return 1;
  133.     r = Bconmap(dev);
  134.     if (r) {
  135.         curbconmap = dev;
  136.         return 1;
  137.     }
  138.     return 0;
  139. }
  140.     
  141. long ARGS_ON_STACK
  142. uiorec(dev)
  143.     int dev;
  144. {
  145.     TRACE(("Iorec(%d)", dev));
  146.     if (dev == 0 && has_bconmap)
  147.         mapin(curproc->bconmap);
  148.     return (long)Iorec(dev);
  149. }
  150.  
  151. long ARGS_ON_STACK
  152. rsconf(baud, flow, uc, rs, ts, sc)
  153.     int baud, flow, uc, rs, ts, sc;
  154. {
  155.     long rsval;
  156.     static int oldbaud = -1;
  157.     int ret_oldbaud = 0;
  158.     IOREC_T *ior;
  159.  
  160.     TRACE(("Rsconf(%d,%d,%d,%d,%d,%d)", baud, flow,
  161.         uc, rs, ts, sc));
  162.  
  163.     if (has_bconmap)
  164.         mapin(curproc->bconmap);
  165.  
  166. #ifndef DONT_ONLY030_THIS
  167. /* Note: the code below must be included, even on a 68030, thanks to a bug
  168.  * in the gcc and mntlib osbind.h file.
  169.  */
  170.  
  171. /*
  172.   If this is an old TOS, try to rearrange things to support
  173.   the following Rsconf() features:
  174.     1. Rsconf(-2, ...) does not return current baud (it crashes)
  175.         -> keep track of old speed in static variable
  176.     2. Rsconf(b, ...) sends ASCII DEL to the modem unless b == -1
  177.         -> make speed parameter -1 if new speed matches old speed
  178.     3. Rsconf() discards any buffered output
  179.         -> use Iorec() to ensure all buffered data was sent before call
  180. */
  181.     else if (tosvers < 0x0104) {
  182.         if (baud == -2) {
  183.             ret_oldbaud = 1;
  184.             baud = -1;
  185.         } else if (baud == oldbaud)
  186.             baud = -1;
  187.         else if (baud > -1)
  188.             oldbaud = baud;
  189.     }
  190. /* This part _is_ necessary on TOS 1.04 */
  191.     if (tosvers <= 0x0104) {
  192.         int attempts = 0;
  193.         short old_head;
  194.         ior = ((IOREC_T *) uiorec(0)) + 1; /* output record */
  195.         old_head = ior->head;
  196.         while (ior->head != ior->tail) {
  197.             if (++attempts >= 50) { /* prevent getting stuck by flow control */
  198.                 if (old_head == ior->head)
  199.                     break;
  200.                 else {
  201.                     old_head = ior->head;
  202.                     attempts = 0;
  203.                 }
  204.             }
  205.             TRACE(("Rsconf() napping until transmit buf empty"));
  206.             nap(200);
  207.         }
  208.     }
  209. #endif /* ONLY030 */
  210.  
  211.     rsval = Rsconf(baud, flow, uc, rs, ts, sc);
  212.     if (ret_oldbaud)
  213.         rsval = (long) oldbaud;
  214.  
  215.     return rsval;
  216. }
  217.  
  218. long ARGS_ON_STACK
  219. bconmap(dev)
  220.     int dev;
  221. {
  222.     int old = curproc->bconmap;
  223.  
  224.     TRACE(("Bconmap(%d)", dev));
  225.  
  226.     if (has_bconmap) {
  227.         if (dev == -1) return old;
  228.         if (dev == -2) return Bconmap(-2);
  229.         if (dev == 0) return 0;  /* the user's just testing */
  230.         if (mapin(dev) == 0) {
  231.             DEBUG(("Bconmap: mapin(%d) failed", dev));
  232.             return 0;
  233.         }
  234.         if (set_auxhandle(curproc, dev) == 0) {
  235.             DEBUG(("Bconmap: Couldn't change AUX:"));
  236.             return 0;
  237.         }
  238.         curproc->bconmap = dev;
  239.         return old;
  240.     }
  241.     return EINVFN;    /* no Bconmap available */
  242. }
  243.  
  244. /*
  245.  * cursconf(): this gets converted into an ioctl() call on
  246.  * the appropriate device
  247.  */
  248.  
  249. long ARGS_ON_STACK
  250. cursconf(cmd, op)
  251.     int cmd, op;
  252. {
  253.     FILEPTR *f;
  254.  
  255.     f = curproc->handle[-1];
  256.     if (!f || !is_terminal(f))
  257.         return EINVFN;
  258.     return
  259.       (*f->dev->ioctl)(f, TCURSOFF+cmd, &op);
  260. }
  261.  
  262.  
  263. long ARGS_ON_STACK
  264. dosound(ptr)
  265.     const char *ptr;
  266. {
  267.     MEMREGION *r;
  268.  
  269.     if (!no_mem_prot && ((long)ptr >= 0)) {
  270.     /* check that this process has access to the memory */
  271.     /* (if not, the next line will cause a bus error) */
  272. #ifdef __TURBOC__
  273.     /* work-around for buggy optimizer */
  274.         char dummy =
  275. #endif
  276.         (void)(*((volatile char *)ptr));
  277. #ifdef __TURBOC__
  278.         UNUSED(dummy);
  279. #endif
  280.     /* OK, now make sure that interrupt routines will have access,
  281.      * too
  282.      */
  283.         r = addr2region((long)ptr);
  284.         if (r && get_prot_mode(r) == PROT_P) {
  285.             DEBUG(("Dosound: changing protection to Super"));
  286.             mark_region(r, PROT_S);
  287.         }
  288.     }
  289.  
  290.     return call_dosound(ptr);
  291. }
  292.  
  293. void
  294. init_xbios()
  295. {
  296.     curbconmap = (has_bconmap) ? (int) Bconmap(-1) : 1;
  297.  
  298.     xbios_tab[0x0c] = midiws;
  299.     xbios_tab[0x0e] = uiorec;
  300.     xbios_tab[0x0f] = rsconf;
  301.     xbios_tab[0x15] = cursconf;
  302.     xbios_tab[0x20] = dosound;
  303.     xbios_tab[0x26] = supexec;
  304.     xbios_tab[0x2c] = bconmap;
  305. }
  306.